package service

import (
	"context"
	"mini-app/config/mysql"
	"mini-app/internal/app/grpc/common"
	"mini-app/internal/dal"
	"mini-app/internal/dao"
	"mini-app/internal/define"
	"mini-app/internal/models"

	"192.168.1.75/go-pkg/errorx"
	"192.168.1.75/go-pkg/helper"
	"192.168.1.75/go-pkg/logx"
	"github.com/shopspring/decimal"
	"gorm.io/gorm"
)

type Goods struct{}

type GoodsListT struct {
	GoodsID     string `json:"goods_id"`
	GoodsName   string `json:"goods_name"`
	GoodsImage  string `json:"goods_image"`
	GoodsType   int    `json:"goods_type"`
	Price       string `json:"price"`
	PickupType  string `json:"pickup_type"`  // 取货方式
	Tag         string `json:"tag"`          // 商品标签
	CornerLabel string `json:"corner_label"` // 商品角标
	GoodsClass  string `json:"goods_class"`  // 分类
	Visible     int    `json:"visible"`      // 是否展示
}

// List 商品列表
// 这里的分类用的是小程序后台单独维护的分类
func (Goods) List(
	ctx context.Context,
	robotID string,
	goodsType int,
	goodsClass string, // 展示分类
	goodsName string,  // 商品名称
	visible int,
	page, limit int,
) (list []GoodsListT, total int64, err error) {
	records := []GoodsListT{}
	if robotID == "" {
		return []GoodsListT{}, 0, errorx.New("设备id不能为空", -1)
	}
	goodsIDs := []string{}
	goodsList, _ := common.GRPC{}.GetGoodsList(ctx, robotID, goodsType, 0, "", goodsName, 1, 0)
	// 初始化新的商品
	for _, record := range goodsList {
		goodsIDs = append(goodsIDs, record.GoodsId)
		if !(dao.GoodsSetting{}).Exists(ctx, dal.Q, robotID, record.GoodsId, "") {
			dao.GoodsSetting{}.Create(ctx, dal.Q, record.GoodsId, robotID, int(record.GoodsType))
		}
		records = append(records, GoodsListT{
			GoodsID:    record.GoodsId,
			GoodsName:  record.GoodsName,
			GoodsImage: record.GoodsImage,
			Price:      decimal.NewFromFloat(record.GoodsPrice).Round(2).StringFixed(2),
			GoodsType:  int(record.GoodsType),
		})
	}
	if len(records) == 0 {
		return []GoodsListT{}, 0, nil
	}
	// 获取商品配置
	// 以零售后台存在的产品为主，所以这里必须以goodsIDs作为过滤
	settings, total, _ := dao.GoodsSetting{}.List(
		ctx,
		dal.Q,
		robotID,
		goodsIDs,
		goodsClass,
		visible,
		page, limit,
	)
	for _, setting := range settings {
		for index, record := range records {
			if record.GoodsID == setting.GoodsID {
				if setting.Visible == 0 {
					setting.Visible = 2
				}
				records[index].Visible = setting.Visible
				records[index].PickupType = setting.PickupType
				records[index].Tag = setting.Tag
				records[index].CornerLabel = setting.CornerLabel
				records[index].GoodsClass = setting.GoodsClass
				list = append(list, records[index])
				break
			}
		}
	}
	if len(list) == 0 {
		return []GoodsListT{}, 0, nil
	}
	return
}

// Set 商品设置
func (Goods) Set(
	ctx context.Context,
	robotID string,
	goodsID string,
	goodsName string,
	pickupType string,  // 取货方式，多个以逗号分隔
	tag string,         // 商品标签
	cornerLabel string, // 商品脚标
	goodsClass string,  // 展示分类
	visible int,        // 是否在小程序展示
) error {
	if robotID == "" {
		return errorx.New("设备id不能为空", -1)
	}
	if goodsID == "" {
		return errorx.New("商品id不能为空", -1)
	}
	if visible == 0 {
		visible = 2
	}
	return dao.GoodsSetting{}.Update(
		ctx,
		dal.Q,
		robotID,
		goodsID, goodsName,
		pickupType,
		tag,
		cornerLabel,
		goodsClass,
		visible,
	)
}

// 批量设置
func (t Goods) SetVisible(
	ctx context.Context,
	goodsID string,
	robotIDs []string,
	visible int, // 是否在小程序展示
) error {

	if goodsID == "" {
		return errorx.New("商品id不能为空", -1)
	}

	if visible != define.State_Yes && visible != define.State_No {
		return errorx.New("visible参数错误", -1)
	}
	db := mysql.NewDB()
	err := db.Transaction(func(tx *gorm.DB) error {
		err := t.ResetVisible(ctx, db, goodsID)
		if err != nil {
			return err
		}

		if len(robotIDs) == 0 {
			return nil
		}

		goodsSettingRepo := dao.NewGoodsSettingRepo(db)

		for _, vRobotID := range robotIDs {
			if vRobotID == "" {
				continue // 有些测试数据vRobotID为空
			}
			item, err := goodsSettingRepo.FindOneByFilter(ctx, &dao.GoodsSettingFilter{
				GoodsID: goodsID,
				RobotID: vRobotID, // 注意，这里不能为长度为0的数组，因为会导致更新全部goodsID对应的goodsSetting
			})
			if err != nil {
				logx.Error(ctx, "GoodsSetting.BatchSet", logx.Any("err", err))
				return err
			}

			if item == nil {
				// 经过讨论后不返回，因为前端在商品下选择机器时，也可以选中没有该商品的机器 return fmt.Errorf("商品配置(%s, %s)不存在", goodsID, vRobotID)
				logx.Warn(ctx, "商品配置(%s, %s)不存在", logx.Any("goodsID", goodsID), logx.Any("vRobotID", vRobotID))
				continue
			}

			err = goodsSettingRepo.UpdateByFilter(ctx, &dao.GoodsSettingFilter{
				GoodsID: goodsID,
				RobotID: vRobotID, // 注意，这里不能为长度为0的数组，因为会导致更新全部goodsID对应的goodsSetting
			}, &models.GoodsSetting{
				Visible: visible,
			})

			if err != nil {
				logx.Error(ctx, "GoodsSetting.BatchSet", logx.Any("err", err))
				return err
			}
		}

		return nil
	})

	if err != nil {
		logx.Error(ctx, "Goods.BatchSet", logx.Any("err", err))
		return err
	}

	return nil
}

func (Goods) ResetVisible(ctx context.Context, tx *gorm.DB, goodsID string) error {
	err := tx.Transaction(func(tx *gorm.DB) error {
		goodsSettingRepo := dao.NewGoodsSettingRepo(tx)
		goodsSettings, _, err := goodsSettingRepo.ListByFilter(ctx, &dao.GoodsSettingListFilter{
			GoodsID: goodsID,
		}, helper.NewPageInfo(1, 100000, nil))

		if err != nil {
			logx.Error(ctx, "GoodsSetting.BatchSet", logx.Any("err", err))
			return err
		}

		for _, v := range goodsSettings {
			if v.Visible == define.State_No {
				continue
			}
			v.Visible = define.State_No

			f := &dao.GoodsSettingFilter{
				GoodsID: v.GoodsID,
				RobotID: v.RobotID,
			}
			err = goodsSettingRepo.UpdateColByFilter(ctx, f, v, dal.Q.GoodsSetting.Visible)
			if err != nil {
				logx.Error(ctx, "GoodsSetting.BatchSet", logx.Any("err", err))
				return err
			}
		}

		return nil
	})

	if err != nil {
		return err
	}
	return nil
}

// ListGoodsSetting 获取商品设置列表
func (Goods) ListGoodsSetting(
	ctx context.Context,
	goodsID string,
	visible int,
) (list []*models.GoodsSetting, total int64, err error) {
	if goodsID == "" {
		return nil, 0, errorx.New("商品id不能为空", -1)
	}

	// 使用DAO层的ListByFilter方法查询
	if visible != 0 && visible != define.State_Yes && visible != define.State_No {
		return nil, 0, errorx.New("visible参数错误", -1)
	}

	goodsSettingRepo := dao.NewGoodsSettingRepo(ctx)
	list, total, err = goodsSettingRepo.ListByFilter(ctx, &dao.GoodsSettingListFilter{
		GoodsID: goodsID,
		Visible: visible,
	}, helper.NewPageInfo(1, 100000, nil))

	if err != nil {
		logx.Error(ctx, "Goods.ListGoodsSetting", logx.Any("err", err))
		return nil, 0, err
	}

	return list, total, nil
}
